package cn.com.dcsgo.service.impl;

import cn.com.dcsgo.config.OSSConfig;
import cn.com.dcsgo.exception.BusinessException;
import cn.com.dcsgo.service.FileService;
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 文件服务实现类
 *
 * @author Dcsgo
 * @since 2025/9/28 17:11
 */
@Slf4j
@Service
public class FileServiceImpl implements FileService {
    @Resource
    private OSSConfig ossConfig;

    @Override
    public String upload(MultipartFile file) {
        // 使用DefaultCredentialProvider方法直接设置AK和SK
        CredentialsProvider credentialsProvider =
                new DefaultCredentialProvider(ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
        // 创建OSSClient实例。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        // 显式声明使用 V4 签名算法
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint("https://" + ossConfig.getEndpoint())
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(ossConfig.getRegion())
                .build();
        // 设置上传到中OSS的文件名
        // 获取原生文件名
        String originalFilename = file.getOriginalFilename();
        LocalDateTime time = LocalDateTime.now();
        DateTimeFormatter dft = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        // 拼装OSS上的存储路径
        String folder = dft.format(time);
        // 在OSS上bucket下的文件名
        String uploadFileName = folder + "/" + originalFilename;
        try {
            InputStream inputStream = file.getInputStream();
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(ossConfig.getBucketName(), uploadFileName, inputStream);
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            //拼装返回路径
            if (result != null) {
                // 示例：https://dcsgo-mall.oss-cn-shanghai.aliyuncs.com/2050/09/28/test.png
                return "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/" + uploadFileName;
            }
        } catch (OSSException oe) {
            log.error("Caught an OSSException, which means your request made it to OSS, but was rejected with an error response for some reason.");
            log.error("Error Message:{}", oe.getErrorMessage());
            log.error("Error Code:{}", oe.getErrorCode());
            log.error("Request ID:{}", oe.getRequestId());
            log.error("Host ID:{}", oe.getHostId());
            throw oe;
        } catch (ClientException ce) {
            log.error("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.error("Error Message:{}", ce.getMessage());
            throw ce;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            // 当OSSClient实例不再使用时，应当调用shutdown方法以释放资源。
            ossClient.shutdown();
        }
        throw new BusinessException("文件上传失败");
    }
}
